using System;
using System.Collections.Generic;
using System.Text;

namespace Axe
{
    public static partial class Utility
    {
        public enum SizeStringFormat
        {
            Full        /* Like: 10Gb 174Mb 546Kb 156 bytes*/,
            RoundToGb   /* Like: 10Gb                      */,
            RoundToMb   /* Like: 10Gb 174Mb                */,
            RoundToKb   /* Like: 10Gb 174Mb 546Kb          */
        };

        static readonly int OneGigabyte = 1073741824;
        static readonly int OneMegabyte = 1048576;
        static readonly int OneKilobyte = 1024;

        #region public static int GetGigabytesCount(int num)
        public static int GetGigabytesCount(int num)
        {
            return num / OneGigabyte;
        } 
        #endregion

        #region public static int GetGigabytesCount(int num, ref int remainder)
        public static int GetGigabytesCount(int num, ref int remainder)
        {
            int gigs = num / OneGigabyte;
            remainder = num % OneGigabyte;
            return gigs;
        } 
        #endregion

        #region public static int GetMegabytesCount(int num)
        public static int GetMegabytesCount(int num)
        {
            return num / OneGigabyte;
        } 
        #endregion

        #region public static int GetMegabytesCount(int num, ref int remainder)
        public static int GetMegabytesCount(int num, ref int remainder)
        {
            int count = num / OneMegabyte;
            remainder = num % OneMegabyte;
            return count;
        }  
        #endregion

        #region public static int GetKilobytesCount(int num)
        public static int GetKilobytesCount(int num)
        {
            return num / OneGigabyte;
        } 
        #endregion

        #region public static int GetKilobytesCount(int num, ref int remainder)
        public static int GetKilobytesCount(int num, ref int remainder)
        {
            int count = num / OneKilobyte;
            remainder = num % OneKilobyte;
            return count;
        }
        #endregion

        public static string GetStringSize(int sizeInBytes, SizeStringFormat format, bool roundRemainder)
        {

            //int rest = sizeInBytes;

            return "";
            //return CreateTextPresentations(gygabytes, megabytes, kylobytes, rest);
        }

        #region private static string CreateTextPresentations(float gb, float mb, float kb, int bytes)
        private static string CreateTextPresentations(float gb, float mb, float kb, int bytes)
        {
            string gbString = "Gb";
            string mbString = "Mb";
            string kbString = "Kb";
            string byteString = "byte(s)";

            StringBuilder sb = new StringBuilder();

            if (gb > 0)
            {
                sb.Append(gb.ToString(":3"));
                sb.Append(gbString);
            }

            if (mb > 0)
            {
                if (sb.Length > 0)
                    sb.Append(' ');
                sb.Append(mb);
                sb.Append(mbString);
            }

            if (kb > 0)
            {
                if (sb.Length > 0)
                    sb.Append(' ');
                sb.Append(kb);
                sb.Append(kbString);
            }

            if (bytes > 0 || sb.Length == 0)
            {
                if (sb.Length > 0)
                    sb.Append(' ');

                sb.Append(bytes);
                sb.Append(byteString);
            }

            return sb.ToString();
        } 
        #endregion

        public static bool IsInRange<T>(T value, T low, T high) where T : IComparable<T>
        {
            return value.CompareTo(low) >= 0 && value.CompareTo(high) <= 0;
        }

        public static bool IsInRange(double value, double low, double high)
        {
            return value >= low && value <= high;
        }

        public static bool IsInRange(int value, int low, int high)
        {
            return value >= low && value <= high;
        }

        public static int ToInt32(string input, int defaultValue)
        {
            int value;
            if (String.IsNullOrEmpty(input))
                return defaultValue;

            if (Int32.TryParse(input, out value))
                return value;

            return defaultValue;
        }

        #region public static bool IsPowOf2(int value)
        public static bool IsPowOf2(int value)
        {
            return ((value & -value) == value);
        } 
        #endregion

        #region public static bool NumberBetween(double num, int bound1, int bound2, double allowance)
        public static bool NumberBetween(double num, int bound1, int bound2, double allowance)
        {
            if (bound1 > bound2)
            {
                int i = bound1;
                bound1 = bound2;
                bound2 = i;
            }

            return (num < bound2 + allowance && num > bound1 - allowance);
        } 
        #endregion

        public static int Range(int min, int max, int value)
        {
            return Math.Min(Math.Max(value, min), max);
        }

        public static double Range(double min, double max, double value)
        {
            return Math.Min(Math.Max(value, min), max);
        }

        public static double Interpolate(double x1, double x2, double y1, double y2, double x)
        {
            return (x - x1) * (y2 - y1) / (x2 - x1) + y1;
        }

        public static double TruncateTo(double value, int precision)
        {
            double val = Math.Pow(10, precision);
            double mulVal = value * val;
            double ceil = Math.Floor(mulVal);
            double divVal = ceil / val;
            return divVal;
        }

        public static int GetMinSignificantDigit(double value)
        {
            for (int i = 0; i < 16; i++)
            {
                double radix = Math.Pow(10, i);

                double newVal = value * radix;
                double remainder = Math.Ceiling(newVal) - newVal;
                if (remainder == 0)
                    return i;
            }

            return 16;
        }


        public static void Swap(ref int leftIdxExpected, ref int rightIdxExpected)
        {
            int temp = rightIdxExpected;
            rightIdxExpected = leftIdxExpected;
            leftIdxExpected = temp;
        }
    }
}
